///*
//package com.thread.threadfirst.marvel.filter;
//
//import com.alibaba.fastjson.JSON;
//import com.alibaba.fastjson.JSONObject;
//import com.fugui.marvel.common.constants.CommonConstants;
//import com.fugui.marvel.common.dto.ResultWrap;
//import com.fugui.marvel.common.utils.JsonMapUtil;
//import com.fugui.marvel.common.utils.URLUtils;
//import com.fugui.marvel.common.utils.zuul.AESUtils4Zuul;
//import com.fugui.marvel.common.utils.zuul.Base64Utils;
//import com.fugui.marvel.common.utils.zuul.RSAUtils4Zuul;
//import com.fugui.marvel.zuul.filter.warpper.JsonHttpServletRequsetWrapper;
//import com.google.common.collect.Lists;
//import com.google.common.collect.Maps;
//import com.netflix.zuul.ZuulFilter;
//import com.netflix.zuul.context.RequestContext;
//import com.netflix.zuul.exception.ZuulException;
//import com.sun.xml.internal.ws.client.RequestContext;
//import com.thread.threadfirst.marvel.zuul.AESUtils4Zuul;
//import com.thread.threadfirst.marvel.zuul.Base64Utils;
//import com.thread.threadfirst.marvel.zuul.RSAUtils4Zuul;
//import com.thread.threadfirst.marvel.zuul.URLUtils;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.http.HttpStatus;
//import org.springframework.stereotype.Component;
//import org.springframework.util.PatternMatchUtils;
//import org.springframework.util.StreamUtils;
//import org.springframework.util.StringUtils;
//
//import javax.servlet.http.HttpServletRequest;
//import java.io.InputStream;
//import java.nio.charset.Charset;
//import java.util.*;
//import java.util.regex.Matcher;
//import java.util.regex.Pattern;
//
//*/
///**
// * @Author zhangchaofeng
// * @Description 验签
// * @Date 19:46 2019/6/10
// **//*
//
//@Slf4j
//@Component
//public class SignFilter extends ZuulFilter {
//    //@Value("${zuul.ignored.routes}")
//    private String[] ignoreRoutes = {"/m2.0/facade/user/fileupload/uploadFile",
//                                     "/m2.0/facade/payment/payNowWithParamsNew",
//                                    "/m2.0/shield"};
//    @Value("${sign.RSAPrivateKey}")
//    private String RSAPrivateKey;
//
//    @Value("${sign.enabled}")
//    private String signEnabled;
//
//    @Override
//    public String filterType() {
//        return "pre";
//    }
//
//    @Override
//    public int filterOrder() {
//        return 0;
//    }
//
//    @Override
//    public boolean shouldFilter() {
//        RequestContext ctx = RequestContext.getCurrentContext();
//        HttpServletRequest request = ctx.getRequest();
//        String uri = request.getRequestURI().toLowerCase();
//        */
///**URI带有 anon 表示为可匿名访问 则不过滤  例如通道的回调以及支付状态的页面接口*//*
//
//        if(PatternMatchUtils.simpleMatch("*anon*", uri) ||
//                PatternMatchUtils.simpleMatch("*shield*", uri)){
//            return false;
//        }
//        if (org.apache.commons.lang3.StringUtils.equals(signEnabled, "true")) {
//            return true;
//        } else {
//            return false;
//        }
//    }
//
//    */
///**
//     * run：过滤器的具体逻辑。
//     * 要把请求参数进行验签（解密）之后传给后续的微服务，首先获取到request，但是在request中只有getParameter()而没有setParameter()方法
//     * 所以直接修改url参数不可行，另外在reqeust中虽然可以使用setAttribute(),但是可能由于作用域（request）的不同，一台服务器中才能getAttribute
//     * 在这里设置的attribute在后续的微服务中是获取不到的，因此必须考虑另外的方式：即获取请求的输入流，并重写，即重写json参数，
//     * ctx.setRequest(new HttpServletRequestWrapper(request) {})，这种方式可重新构造上下文中的request
//     *
//     * @return
//     *//*
//
//    @Override
//    public Object run() throws ZuulException {
//        log.info("---------------into signFilter-----------");
//        RequestContext context = RequestContext.getCurrentContext();
//        try {
//            HttpServletRequest request = context.getRequest();
//            boolean isIgnore = false;
//            for (String str : ignoreRoutes) {
//                if (request.getRequestURI().contains(str)) {
//                    isIgnore = true;
//                    break;
//                }
//            }
//            if (isIgnore) {
//                context.setResponseStatusCode(HttpStatus.OK.value());
//                context.setSendZuulResponse(true);
//                return null;
//            }
//
//            //请求的方法
//            String method = request.getMethod();
//            log.info("{}>>>{}", method, request.getRequestURL());
//
//            InputStream inputStream = request.getInputStream();
//            String body = StreamUtils.copyToString(inputStream, Charset.forName("UTF-8"));
//            if (StringUtils.isEmpty(body)) {
//                body = "{}";
//            } else if(org.apache.commons.lang3.StringUtils.isNotBlank(body) &&
//                    !body.startsWith("{") && !body.endsWith("}")) {
//                StringBuilder stb = new StringBuilder(body);
//                stb.insert(0,"{\"");
//                stb.append("\"}");
//                body = stb.toString();
//                body = body.replaceAll("=","\":\"");
//                body = body.replaceAll("&","\",\"");
//            }
//
//
//            if ("GET".equals(method)) {
//                List<String> param;
//                Map<String, Object> paramMap = Maps.newTreeMap(
//                        new Comparator<String>() {
//                            @Override
//                            public int compare(String o1, String o2) {
//                                //升序排序
//                                return o1.compareTo(o2);
//                            }
//                        }
//                );
//
//                // 关键步骤，一定要get一下,下面才能取到值requestQueryParams
//                request.getParameterMap();
//                Map<String, List<String>> requestQueryParams = context.getRequestQueryParams();
//                Enumeration enu = request.getParameterNames();
//                while (enu.hasMoreElements()) {
//                    param = Lists.newArrayList();
//                    String paraName = (String) enu.nextElement();
//                    System.out.println(paraName + ": " + request.getParameter(paraName));
//                    param.add(request.getParameter(paraName));
//                    requestQueryParams.put(paraName, param);
//                    paramMap.put(paraName, request.getParameter(paraName));
//                }
//
//                if (!paramMap.containsKey("sign") || !paramMap.containsKey("timestamp") || !paramMap.containsKey("key")) {
//                    //buildResponse(context, ResultWrap.init(CommonConstants.FALIED, "参数异常"));
//                    log.info("======================={}={}缺少验签参数========================",request.getMethod(),request.getRequestURL());
//                    if(requestQueryParams != null) {
//                        context.setRequestQueryParams(requestQueryParams);
//                    }
//                    context.setResponseStatusCode(HttpStatus.OK.value());
//                    context.setSendZuulResponse(true);
//                    return null;
//                }
//                //TODO  后续进行时间戳的时效性的判断
//                //拿出排完序的参数，拼装起来，进行验签
//                StringBuffer stb = new StringBuffer();
//                paramMap.forEach((k, v) -> {
//                    if (!"sign".equals(k) && !"timestamp".equals(k) && !"key".equals(k)) {
//                        stb.append(k + "=" + v + "&");
//                    }
//
//                });
//                stb.deleteCharAt(stb.length() - 1);
//
//                //拼装完成，先用RSA秘钥解密出AES的key，再用AES的key对排序后的参数加密，然后对比
//                String AESKey = new String(RSAUtils4Zuul.decryptByPrivateKey(Base64Utils.decode(paramMap.get("key").toString().replace(" ","")),RSAPrivateKey));
//
//                String encrypt = AESUtils4Zuul.aesEncrypt(stb.toString(),AESKey);
//                encrypt = replaceBlank(encrypt);
//                String base64Sign = replaceBlank(paramMap.get("sign").toString());
//                if (!org.apache.commons.lang3.StringUtils.equals(encrypt, base64Sign)) {
//                    buildResponse(context, ResultWrap.init(CommonConstants.FALIED, "签名异常"));
//                    return null;
//                }
//                if(requestQueryParams != null){
//                    context.setRequestQueryParams(requestQueryParams);
//                }
//
//            } else if ("POST".equals(method) || "PUT".equals(method)) {
//                // post和put需重写HttpServletRequestWrapper
//                JSONObject requestBody = JSONObject.parseObject(body);
//                System.out.println("requestBody.getString(\"key\") = " + requestBody.getString("key"));
//
//                if (StringUtils.isEmpty(requestBody.getString("sign")) || StringUtils.isEmpty(requestBody.getString("timestamp")) || StringUtils.isEmpty(requestBody.getString("key"))) {
//                    //buildResponse(context, ResultWrap.init(CommonConstants.FALIED, "参数异常"));
//                    log.info("======================={}={}缺少验签参数========================",request.getMethod(),request.getRequestURL());
//                    context.setResponseStatusCode(HttpStatus.OK.value());
//                    context.setSendZuulResponse(true);
//                    return null;
//                }
//
//                if (!checkSign(requestBody)) {
//                    buildResponse(context, ResultWrap.init(CommonConstants.FALIED, "签名异常"));
//                    return null;
//                }
//
//                if (requestBody.containsKey("sign")) {
//                    requestBody.remove("sign");
//                }
//                if (requestBody.containsKey("timestamp")) {
//                    requestBody.remove("timestamp");
//                }
//                if (requestBody.containsKey("key")) {
//                    requestBody.remove("key");
//                }
//
//                String reqBody = requestBody.toString();
//
//                log.info(reqBody);
//
//                context.setRequest(new JsonHttpServletRequsetWrapper(request, JsonMapUtil.toHashMap(reqBody)));
//
//            }
//        } catch (Exception e) {
//            log.error("{}",e);
//            buildResponse(context, ResultWrap.init(CommonConstants.SC_FORBIDDEN, "解析签名异常~"));
//        }
//        context.setResponseStatusCode(HttpStatus.OK.value());
//        context.setSendZuulResponse(true);
//        return null;
//    }
//
//    private boolean checkSign(JSONObject requestBody) throws Exception {
//        Map<String, String> dataParam = new HashMap<>();
//        for (Map.Entry<String, Object> item : requestBody.entrySet()) {
//            String key = item.getKey();
//            Object value = item.getValue();
//            dataParam.put(key, String.valueOf(value));
//        }
//
//        List<Map.Entry<String, String>> list = new ArrayList<>(dataParam.entrySet());
//        Collections.sort(list,
//                new Comparator<Map.Entry<String, String>>() {
//                    //升序排序
//                    @Override
//                    public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
//                        return o1.getKey().compareTo(o2.getKey());
//                    }
//                });
//        String AESKey = null;
//        String timestamp = null;
//        StringBuffer temp = new StringBuffer();
//        for (Map.Entry<String, String> mapping : list) {
//            if ("sign".equals(mapping.getKey())) {
//                continue;
//            }
//            if ("key".equals(mapping.getKey())) {
//                AESKey = URLUtils.URLDecoderString(mapping.getValue());
//
//            } else if ("timestamp".equals(mapping.getKey())) {
//                timestamp = mapping.getValue();
//            } else {
//                temp.append(mapping.getKey() + "=" + String.valueOf(mapping.getValue()));
//                temp.append("&");
//            }
//
//        }
//        temp.deleteCharAt(temp.length() - 1);
//        //TODO 后续可进行判断时间戳的有效性，控制在10秒以内
//        //拿到key 进行RSA解密，然后在调用解密后的key对排序后的参数进行加密，和sign进行比较
//        //AESKey = new String(AESUtils.base642Byte(AESKey));
//        String decryptKey = new String(RSAUtils4Zuul.decryptByPrivateKey(Base64Utils.decode(AESKey), RSAPrivateKey));
//        String tempSign = AESUtils4Zuul.aesEncrypt(temp.toString(),decryptKey);
//        tempSign = replaceBlank(tempSign);
//        log.info("decryptKey={},AESKey={},sign={}", decryptKey, AESKey, tempSign);
//        String base64Sign = URLUtils.URLDecoderString(dataParam.get("sign"));
//        base64Sign = replaceBlank(base64Sign);
//        if (!org.apache.commons.lang3.StringUtils.equals(base64Sign, tempSign)) {
//            return false;
//        }
//        return true;
//    }
//
//    */
///**
//     * 去除字符串中的空格、回车、换行符、制表符
//     * @param str
//     * @return
//     *//*
//
//    private String replaceBlank(String str) {
//        String ret = "";
//
//        if (str != null) {
//
//            Pattern pattern = Pattern.compile("\\s*|\t|\r|\n");
//
//            Matcher m = pattern.matcher(str);
//
//            ret = m.replaceAll("");
//
//        }
//        return ret;
//    }
//
//    private void buildResponse(RequestContext context, Map<String, Object> resMsg) {
//        context.setResponseBody(JSON.toJSONString(resMsg));
//        context.getResponse().setContentType("application/json;charset=UTF-8");
//        context.setSendZuulResponse(false);
//    }
//
//
//    public static void main(String[] args) {
//        //W4jhawj/zAG8iKB7aXxwW7Q+Vd6V9oAHIC9fhwAAHKmkv2BIFMEsx/q2z+IQLHhr9/cSwoO8+F1ednfK9ubS0g==
//        //Kn1BxP5MqGHyHHAEnIJoNPCSIF1fUnjhjZIuFs7g4kg=
//        //Kn1BxP5MqGHyHHAEnIJoNPCSIF1fUnjhjZIuFs7g4kg%3D
//
//        //key NuuTuORgfiKNobAlYVUygLNgfSz5nHmoFBvvb4dgBANxle2PIwgHCG8JXL5ODLDrEjyExGqZPHDYTV%2BTtcqs%2Bw%3D%3D
//        //Slm4%2FQ71%2Baxf8S6oaVjNw8sPt06QksueEB0%2BXms5ioM%3D
//
//        String urlEncoderString = URLUtils.getURLEncoderString("Slm4/Q71+axf8S6oaVjNw8sPt06QksueEB0+Xms5ioM=");
//        //String deCode = URLUtils.URLDecoderString("Kn1BxP5MqGHyHHAEnIJoNPCSIF1fUnjhjZIuFs7g4kg=");
//        System.out.println(urlEncoderString);
//        //System.out.println(deCode);
//
//    }
//
//}
//*/
